/*************************************************************************
* Copyright(C),2017,ZDC Corporation.
* All right reserved.
* 
* File Name: ser_mod.c
* Description:
* Author: madechuan
* Mail: mdc@zcom.nj
* Created Time: 2017年11月03日 星期五 12时59分55秒
************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <asm/uaccess.h>

dev_t devno;
int major = 200;
int minor = 0;
struct cdev cdev;
int my_open(struct inode *inode, struct file *file)
{
    printk("my_open()\n");
    return 0;
} 
int my_release(struct inode *inode, struct file *file)
{
    printk("my_release()\n");
    return 0;
}
unsigned char kbuf[129];
unsigned long ktickbuf[127];
ssize_t my_read (struct file *file, char __user *buf, size_t size, loff_t *pos)
{
    #if 0
    if(size  >   strlen(ktickbuf))
    {
        size = strlen(ktickbuf) ;
    }
    #endif
    ktickbuf[0] = jiffies;
    printk("test :ktickbuf is  %lu\n",ktickbuf[0]);
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,3,8)
    if(raw_copy_to_user(buf, ktickbuf, size))
#else
    if(copy_to_user(buf, ktickbuf, size))
#endif
    {
        return -EFAULT;
    }
    printk("systick has been sent to server\n");
    return size;
}
ssize_t my_write (struct file *file, const char __user *buf, size_t size, loff_t *pos)
{
    int i;
    int tcplen = 0;
    int iplen = 0;
    int lowlen = 0;
    if(size > sizeof(kbuf)-1)
    {
        size = sizeof(kbuf) -1;
    }
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,3,8)
    if(raw_copy_from_user(kbuf, buf, size))
#else
    if(copy_from_user(kbuf, buf, size))
#endif
    {
        return -EFAULT ;
    }
    kbuf[size]='\0';
#if 0
    for(i=0; i<(34+tcplen); ++i)
    {
        printk(" %02x", kbuf[i]);
        if( (i + 1) % 16 == 0 )
        {
            printk("\n");
        }
    }
    printk("\n");
#endif
    printk("Dst MAC Address:");
    for (i=0; i<6; i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    printk("Src MAC Address:");
    for (i=6; i<12; i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    iplen = (kbuf[14] & 0x0f) * 4;//ip报头的长度为其第15个字节的低四位X4
    printk("IP Header Length is %d\n",iplen);
    printk("Src IP Address:");
    for (i=26; i<30; i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    printk("Dst IP Address:");
    for (i=30; i<34; i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    tcplen = (((kbuf[(14+iplen+12)]>>4)&0x0f)*4);//tcp报头的长度为tcp头的第13个字节
    printk("TCP Header:");
    printk("Tcp header length is %d\n",tcplen);
    for (i=(14+iplen); i<(34+tcplen); i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    lowlen = 14+iplen+tcplen;
    printk("Http Version:");
    for (i=(lowlen); i<(lowlen+8); i++)
    {
        printk(" %02x", kbuf[i]);
    }
    printk("\n");
    return size;
}
struct file_operations  fops ={
    .owner= THIS_MODULE,
    .open= my_open,  //fd = open("/dev/led",O_RDWR)
    .release = my_release,      //close();
    .read = my_read,
    .write = my_write,
};
int my_init(void)
{
    int ret;
    printk("my_init()\n");
    ret = register_chrdev(major,"mdc", &fops);
    if(ret)
    {
        return ret;
    }
    return 0;
}
void my_exit(void)
{
    printk("my_exit()\n");
    unregister_chrdev(major, "mdc");
    return ;
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
